/**
 * Copyright (C) BFH www.bfh.ch 2011
 * Code written by: Patrick Dobler, Marc Folly
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ch.bfh.ti.kybernetik.engine.controller;

import java.util.List;
import java.util.Observer;

import ch.bfh.ti.kybernetik.engine.controller.lightBulb.LightBulbController;
import ch.bfh.ti.kybernetik.engine.controller.roboter.RoboterConstruction;
import ch.bfh.ti.kybernetik.engine.controller.roboter.RoboterController;
import ch.bfh.ti.kybernetik.engine.model.LightBulb;
import ch.bfh.ti.kybernetik.engine.model.Roboter;
import ch.bfh.ti.kybernetik.engine.model.RoboterMove;
import ch.bfh.ti.kybernetik.lego.ki.RoboterKI;

/**
 * The actual Simulating Engine which is a Runnable Thread and Observers are
 * able to subscbribe to
 * 
 * @author pado
 * 
 */
public interface Simulator extends Runnable {

	/**
	 * Get the current speed of the simulation defined by the amount of time the
	 * simulation-thread sleeps
	 * 
	 * @return the current simulator thread sleeps time
	 */
	public abstract int getSimulatorSpeed();

	/**
	 * Set the current speed of the simulation defined by the amount of time the
	 * simulation-thread sleeps
	 * 
	 * @param the
	 *            simulator thread sleeps time
	 */
	public abstract void setSimulatorSpeed(int simulatorSpeed);

	/**
	 * Set the deltaT value which defines the cycle modification factor of the
	 * {@link RoboterMove}
	 * 
	 * @param deltaT
	 */
	public abstract void setDeltaT(double deltaT);

	/**
	 * Get the deltaT value which defines the cycle modification factor of the
	 * {@link RoboterMove}
	 */
	public abstract double getDeltaT();

	/**
	 * Register a new {@link Observer} which sends events defined by the
	 * possible classes in the package
	 * ch.bfh.ti.kybernetik.engine.controller.observerCommands
	 * 
	 * @param observer
	 */
	public abstract void addObserver(Observer observer);

	/**
	 * Defines whether the Simulation is running (true) or not (false)
	 * 
	 * @param set
	 *            the value whether the Simulation is running or not
	 */
	public abstract void setSimulating(boolean simulationRunning);

	/**
	 * Get a List of the current {@link Roboter} instances in the Simulation
	 * 
	 * @return List of all the {@link Roboter} instances in the Simulation
	 */
	public abstract List<Roboter> getRoboterList();

	/**
	 * Get a List of the current {@link LightBulb} instances in the Simulation
	 * 
	 * @return List of all {@link LightBulb} instances in the Simulation
	 */
	public abstract List<LightBulb> getLightBulbList();

	/**
	 * Remove a {@link Roboter} from the Simulation
	 * 
	 * @param roboter
	 *            to remove
	 */
	public abstract void removeRoboter(Roboter roboter);

	/**
	 * Returns the {@link RoboterKI} for the given {@link Roboter}
	 * 
	 * @param roboter
	 *            the {@link Roboter} instance
	 * @return the {@link RoboterKI} for the given {@link Roboter}
	 */
	public RoboterKI getRoboterKIForRoboter(Roboter roboter);

	/**
	 * Returns the {@link RoboterConstruction} for the given {@link Roboter}
	 * 
	 * @param roboter
	 *            the {@link Roboter} instance
	 * @return the {@link RoboterConstruction} for the given {@link Roboter}
	 */
	public RoboterConstruction getRoboterConstructionForRoboter(Roboter roboter);

	/**
	 * Changes the current {@link RoboterKI} of the given {@link Roboter}
	 * 
	 * @param roboter
	 *            to change the {@link RoboterKI}
	 * @param roboterKI
	 *            the new {@link RoboterKI}
	 */
	public void changeRoboterKIForRoboter(Roboter roboter, RoboterKI roboterKI);

	/**
	 * Get all available {@link RoboterKI} instances
	 * 
	 * @return a List of all available {@link RoboterKI}
	 */
	

	abstract void iterateRoboterControllers(ThreadSafeIterationAction<RoboterController> action);

	abstract void iterateLightBulbControllers(ThreadSafeIterationAction<LightBulbController> action);

	/**
	 * Remove a {@link LightBulb} from the Simulation
	 * 
	 * @param lightBulb
	 *            to remove
	 */
	public abstract void removeLightBulb(LightBulb lightBulb);

	/**
	 * Add a new {@link RoboterController}
	 * 
	 * @param roboterController
	 * @return true if the {@link RoboterController} was added otherwise false
	 */
	public abstract boolean addRoboterController(RoboterController roboterController);

	/**
	 * Add a new {@link LightBulbController}
	 * 
	 * @param lightBulbController
	 * @return true if the {@link LightBulbController} was added otherwise false
	 */
	public abstract boolean addLightBulbController(LightBulbController lightBulbController);

	/**
	 * 
	 * @param width
	 *            of the simulation
	 */
	public abstract void setWidth(int width);

	/**
	 * 
	 * @param height
	 *            of the simulation
	 */
	public abstract void setHeight(int height);

	/**
	 * 
	 * @return the height of the Simulation
	 */
	public abstract int getHeight();

	/**
	 * 
	 * @return the width of the Simulation
	 */
	public abstract int getWidth();

}